﻿using System;
using System.Collections.Generic;
using System.Text;

namespace WorkNodeFramework
{
    public class SelectQuery : SelectQuery<SelectQuery>
    {
        public SelectQuery()
            :base()
        {
        }

        public SelectQuery(params IQueryExpression[] expressions)
            :base(expressions)
        {
        }

        public SelectQuery(params string[] expressions)
            : base(expressions)
        {
        }
    }

    public abstract class SelectQuery<T>:Query<T>
        where T:SelectQuery<T>
    {
        int top = -1;
        bool distinct = false;
        List<IQueryExpression> queryList = new List<IQueryExpression>();
        List<IOrderBy> orderList = new List<IOrderBy>();

        internal SelectQuery()
        {
        }

        internal SelectQuery(params IQueryExpression[] expressions)
        {
            queryList.AddRange(expressions);
        }

        internal SelectQuery(params string[] expressions)
        {
            foreach(string exp in expressions)
                queryList.Add(new StringQueryExpression(exp));
        }

        internal int WithTop {
            get {
                return top;
            }
        }

        internal bool WithDistinct {
            get {
                return distinct;
            }
        }

        internal List<IOrderBy> OrderList {
            get {
                return orderList;
            }
        }

        public T Top(int top) {
            this.top = top;
            return (T)this;
        }

        public T Distinct() {
            this.distinct = true;
            return (T)this;
        }

        public T Order(Column column, OrderByEnum orderBy)
        {
            foreach (IOrderBy order in orderList)
                if ((order is ColumnOrderBy) && ((ColumnOrderBy)order).Column.Equals(column))
                {
                    order.OrderBy = orderBy;
                    return (T)this;
                }
            orderList.Add(new ColumnOrderBy(column, orderBy));
            return (T)this;
        }

        public T Order(string columnName, OrderByEnum orderBy)
        {
            foreach (IOrderBy order in orderList)
                if ((order is ColumnNameOrderBy) && (string.Compare(((ColumnNameOrderBy)order).ColumnName,columnName)==0))
                {
                    order.OrderBy = orderBy;
                    return (T)this;
                }
            orderList.Add(new ColumnNameOrderBy(columnName, orderBy));
            return (T)this;
        }

        public T Orders(params Column[] columns)
        {
            foreach (Column col in columns)
                Order(col, OrderByEnum.ASC);
            return (T)this;
        }

        public T Orders(params string[] columns)
        {
            foreach (string col in columns)
                Order(col, OrderByEnum.ASC);
            return (T)this;
        }

        internal List<IQueryExpression> QueryList
        {
            get
            {
                return queryList;
            }
        }
    }
}
